import uuid
import inspect
import cPickle
from operator import *
from data_struct import *


class Opnode(object):
	"""docstring for """
	def __init__(self, v,c=None):
		self.v = v
		self.c = c
	def __str__(self):
		return str(self.v)
	def __eq__(self,other):
		return self.v==other
	def __ne__(self,other):
		return self.v<>other
	def __gt__(self,other):
		return self.v>other
	def __lt__(self,other):
		return self.v<other
	def __ge__(self,other):
		return self.v>=other
	def __le__(self,other):
		return self.v<=other

	def __contains__(self,other):
		if self.c in ["IP"]:
			if type(other)==list:
				for k in other:
					if  eval(self.c)(self.v) in eval(self.c)(k):
						return True
				return False
			else:
				return  eval(self.c)(self.v) in eval(self.c)(other)
		else:
			return self.v in other

	def not__contains__(self,other):
		return not self.contains(other)


class Operation(object):
	"""docstring for Operation"""
	def __init__(self):
		self.op=self.init_op()
		pass
	def init_op(self):
		op={
		"==":"__eq__",
		"!=":"__ne__",
		">":"__gt__",
		"<":"__lt__",
		">=":"__ge__",
		"<=":"__le__",
		"in":"__contains__",
		"!in":"not__contains__"	
		}
		return op
	def compare(self,v,op_str,tv,c=None):
		func=getattr(Opnode, self.op[op_str])
		return func(Opnode(v,c),tv)

	def is_legal(self,op_str):
		if op_str in self.op:
			return True
		raise ValueError("%s error"%(self.__class__.__name__))
		return False

class Subject(object):
	pass
class Resource(object):
	pass
class Condition(object):
	pass

class Action(object):
	"""docstring for Operation"""
	def __init__(self):
		self.ac=self.init_ac()
		pass
	def init_ac(self):
		ac={
		"get":True,
		"put":True,
		"del":True,
		"update":True,
		"list":True,
		"head":True
		}
		return ac

	def is_legal(self,ac_str):
		
		if ac_str in self.ac:
			return True
		raise ValueError("%s error"%(self.__class__.__name__))
		return False


class Attribute(object):
	"""docstring for Attribute"""
	def __init__(self):
		self.attr_info=self.init_attr()
		pass

	def init_attr(self):
		attr_info={}
		attr_info['Subject']={"ip":"IP","port":"Port","protocol":"str","user_name":"str","user_group":"str","auth_token":"str"}
		attr_info['Resource']={"owner":"str","type":"str","name":"str","container":"str","create_time":"Time","modify_time":"Time"}
		attr_info['Condition']={"count":"int","rate":"float","time":"Time","interval":"float"}
		return attr_info
	def check_type(self,t,v):
		return str(eval(t)(v))

	def is_legal(self,cls,k,v):
		t=self.get_legal_attr(self.get_var_type(cls))
		#if k in t and self.get_var_type(v)==t[k]:
		if k in t:
			self.check_type(t[k], v)
			return True
		raise ValueError("%s error"%(self.__class__.__name__))

	def conver_value(self,cls,k,v):
		t=self.get_legal_attr(self.get_var_type(cls))
		return self.check_type(t[k], v)


	def get_legal_attr(self,cls_name):
		return self.attr_info[cls_name]

	@staticmethod
	def get_var_type(c):
		if inspect.isclass(c):
			return c().__class__.__name__
		return c.__class__.__name__

	@staticmethod
	def get_var_attr(ins):
		return ins.__dict__

class Auth(object):
	"""docstring for Auth"""
	def __init__(self):
		super(Auth, self).__init__()
		self.auth_db=self.init_auth()

	def init_auth(self):
		auth={}
		auth["admin:admin"]={"url":"$HOST/v1/AUTH_admin","key":"admin"}
		auth["test:test1"]={"url":"$HOST/v1/AUTH_test","key":"test1"}
		auth["test:test2"]={"url":"$HOST/v1/AUTH_test","key":"test2"}
		auth["test2:tester"]={"url":"$HOST/v1/AUTH_test2","key":"tester"}
		return auth

	def auth(self,a,u,k):
		uid=a+":"+u
		if uid in self.auth_db:
			if self.auth_db[uid]["key"]==k:
				return True
		return False

	def add_user(self,a,u,k,url):
		uid=a+":"+u
		self.auth_db[uid]={"url":url,"key":key}

	def del_user(self,a,u):
		uid=a+":"+u
		self.auth_db.pop(uid)

class Policy(object):
	"""docstring for Policy"""

	def __init__(self,id):
		self.id=id
		self.op_checker=Operation()
		self.attr_checker=Attribute()
		self.act_checker=Action()
		self.p={"Subject":{},"Resource":{},"Condition":{},"Action":[],"Decision":[],"Owenr":self.id,"Global":0,"id":str(uuid.uuid1())}
		self.status=True
		pass



	def set_attr(self,cls,attr,op,value):
		if type(value)!=list:
			if self.attr_checker.is_legal(cls, attr, value) and self.op_checker.is_legal(op):
				i={}
				i["op"]=op
				i["value"]=self.attr_checker.conver_value(cls, attr, value)
				tp=self.attr_checker.get_var_type(cls)
				if attr not in self.p[tp]:
					self.p[tp][attr]=[]
				self.p[tp][attr].append(i)
				return True
		else:
			if self.op_checker.is_legal(op):
				vls=[]
				for v in value:
					if self.attr_checker.is_legal(cls,attr,v):
						vls.append(self.attr_checker.conver_value(cls, attr, v))
						continue
				i={}
				i["op"]=op
				i["value"]=vls
				tp=self.attr_checker.get_var_type(cls)
				if attr not in self.p[tp]:
					self.p[tp][attr]=[]
				self.p[tp][attr].append(i)
				return True
		
	def set_act(self,act):
		if type(act)==str:
			act=act.lower()
			if self.act_checker.is_legal(act):
				self.p["Action"].append(act)
		if type(act)==list:
			for at in act:
				at=at.lower()
				if self.act_checker.is_legal(at):
					self.p["Action"].append(at)
		self.p["Action"]=list(set(self.p["Action"]))
		return True

	def set_dec(self,dec):
		self.p["Decision"]=dec

	def set_global(self,g):
		self.p["Global"]=1 if g==True else 0


	def get_attr(self,cls,attr):
		pass

	def del_attr(self,cls,attr):
		pass

	def update_attr(self,cls,attr,op,value):
		pass

	def submit(self):
		
		f=open("test.po","w")
		cPickle.dump(self.p,f)
		f.close()

if __name__ == '__main__':

	res=[]
	a=Subject()
	c=Condition()
	p=Policy("aaa")
	r=Resource()
	p.set_attr(Condition, "count", "<=", 10.0)
	p.set_attr(Subject, "ip", "!=", "8.8.8.8")
	p.set_attr(Subject, "ip", "in", "0.0.0.0/0")
	p.set_attr(a, "port", "in", [111,80])
	p.set_act("Get")
	p.set_act("Put")
	p.set_act(["get","put"])
	p.set_attr(r,"create_time",">","2012-01-01")
	p.set_attr(r,"create_time","<","2014-01-01")
	p.set_dec("ALLOW")
	res.append(p.p)
	p=Policy("aaa")
	p.set_act("PUT")
	p.set_dec("META")
	p.set_global(True)
	res.append(p.p)
	"""
	for i in range(0,100):
		p=Policy("aaa")
		p.set_attr(Subject, "ip", "!=", "8.8.8.8")
		p.set_attr(Subject, "ip", "in", "0.0.0.0/0")
		p.set_attr(a, "port", "in", [111,80])
		p.set_act("head")
		p.set_dec("DENY")
		p.set_global(True)
		res.append(p.p)
	"""
	print len(res)
	import cPickle
	f=open("test.po","w")
	cPickle.dump(res,f)
	f.close()